package com.youku.expression.ast;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import com.youku.expression.Token;
import com.youku.expression.environment.Environment;

/**
 * if语句
 * 
 * @author loda
 *
 */
public class IfStatementAst extends Ast {

	public IfStatementAst(Token token, Ast... asts) {
		super(token, asts);
	}

	public IfStatementAst(Ast... asts) {
		super(asts);
	}

	/**
	 * if条件
	 * 
	 * @return
	 */
	public Ast ifCondition() {
		return getChild(0);
	}

	/**
	 * if执行体
	 * 
	 * @return
	 */
	public Ast ifBody() {
		return getChild(1);
	}

	/**
	 * elsif语句
	 * 
	 * @return
	 */
	public List<Ast> elsifStatement() {
		if (childSize() > 3) {
			int start = 2;
			int end = childSize() - 2;
			List<Ast> stats = new LinkedList<>();

			for (int i = start; i <= end; i++) {
				stats.add(getChild(i));
			}
			return stats;

		} else {
			return Collections.emptyList();
		}

	}

	/**
	 * else执行语句
	 * 
	 * @return
	 */
	public Ast elseBody() {
		if (childSize() > 2)
			return getLastChild();
		else
			return null;
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();

		List<Ast> stmt = elsifStatement();
		for (int i = 0; i < stmt.size(); i++) {

			if (stmt.get(i) instanceof OpAst) {
				builder.append("elsif").append(stmt.get(i)).append(stmt.get(++i));
			}
		}
		Ast ast = elseBody();
		if (ast != null) {
			builder.append("else" + ast);
		}
		return new StringBuilder().append("if").append(ifCondition()).append(ifBody()).append(builder).toString();
	}

	@Override
	public Object eval(Environment environment) {
		boolean success = (boolean) ifCondition().eval(environment);

		if (success) {
			return ifBody().eval(environment);
		}

		List<Ast> stmt = elsifStatement();
		for (int i = 0; i < stmt.size(); i++) {
			Ast ast = stmt.get(i);
			if (ast instanceof OpAst) {
				success = (boolean) ast.eval(environment);

				if (success) {
					return stmt.get(++i).eval(environment);
				}
			}
		}

		Ast elseBody = elseBody();
		if (elseBody != null) {
			return elseBody.eval(environment);
		}

		return null;
	}

}
